﻿using System;

namespace Songhay
{
    /// <summary>
    /// Static members for type handling.
    /// </summary>
    public static class FrameworkType
    {
        /// <summary>
        /// Returns <c>true</c> when the specified value
        /// is an empty array, not an array or null.
        /// </summary>
        /// <param name="frameworkValue">The specified value.</param>
        public static Boolean ArrayIsNullOrEmptyOrNotArray(Object frameworkValue)
        {
            if (frameworkValue == null) return true;
            if (frameworkValue is Array)
            {
                Array array = frameworkValue as Array;
                return (array.Length == 0);
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// Converts Unix time stamps
        /// to <see cref="System.DateTime"/>.
        /// </summary>
        /// <param name="unixTime">A <see cref="System.Double"/>.</param>
        /// <returns>A <see cref="System.DateTime"/>.</returns>
        public static DateTime DateTimeFromUnixTime(double unixTime)
        {
            return (new DateTime(1970, 1, 1, 0, 0, 0)).AddSeconds(unixTime);
        }

        /// <summary>
        /// Converts the current time
        /// to a Unix time stamp.
        /// </summary>
        /// <returns>A <see cref="System.Double"/>.</returns>
        public static double DateTimeToUnixTime()
        {
            return (DateTime.UtcNow
                - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
        }

        /// <summary>
        /// Converts a <see cref="System.DateTime"/>
        /// to a Unix time stamp.
        /// </summary>
        /// <param name="dateValue">The <see cref="System.DateTime"/>.</param>
        /// <returns>A <see cref="System.Double"/>.</returns>
        public static double DateTimeToUnixTime(DateTime dateValue)
        {
            return (dateValue.ToUniversalTime()
                - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds;
        }

        /// <summary>
        /// Tries to convert the specified value
        /// to the <see cref="System.Nullable"/> return type.
        /// </summary>
        /// <param name="frameworkValue">
        /// The specified <see cref="System.Object"/> box.
        /// </param>
        /// <returns>
        /// Always returns a <see cref="System.Nullable"/>
        /// as parse failure means <c>HasValue</c>
        /// is false.
        /// </returns>
        public static Boolean? ParseBoolean(Object frameworkValue)
        {
            bool bln;
            String s = (frameworkValue != null) ? frameworkValue.ToString() : String.Empty;
            if (Boolean.TryParse(s, out bln)) return bln;
            else return new Boolean?();
        }

        /// <summary>
        /// Tries to convert the specified value
        /// to the <see cref="System.Nullable"/> return type.
        /// </summary>
        /// <param name="frameworkValue">
        /// The specified <see cref="System.Object"/> box.
        /// </param>
        /// <returns>
        /// Always returns a <see cref="System.Nullable"/>
        /// as parse failure means <c>HasValue</c>
        /// is false.
        /// </returns>
        public static Byte? ParseByte(Object frameworkValue)
        {
            Byte b;
            String s = (frameworkValue != null) ? frameworkValue.ToString() : String.Empty;
            if (Byte.TryParse(s, out b)) return b;
            else return new Byte?();
        }

        /// <summary>
        /// Tries to convert the specified value
        /// to the <see cref="System.Nullable"/> return type.
        /// </summary>
        /// <param name="frameworkValue">
        /// The specified <see cref="System.Object"/> box.
        /// </param>
        /// <returns>
        /// Always returns a <see cref="System.Nullable"/>
        /// as parse failure means <c>HasValue</c>
        /// is false.
        /// </returns>
        public static DateTime? ParseDateTime(Object frameworkValue)
        {
            DateTime d;
            String s = (frameworkValue != null) ? frameworkValue.ToString() : String.Empty;
            if (DateTime.TryParse(s, out d)) return d;
            else return new DateTime?();
        }

        /// <summary>
        /// Tries to convert the specified value
        /// to the <see cref="System.Nullable"/> return type.
        /// </summary>
        /// <param name="frameworkValue">
        /// The specified <see cref="System.Object"/> box.
        /// </param>
        /// <param name="formatExpression">
        /// The string format expression.
        /// </param>
        /// <returns>
        /// Always returns a <see cref="System.Nullable"/>
        /// as parse failure means <c>HasValue</c>
        /// is false.
        /// </returns>
        public static String ParseDateTimeWithFormat(Object frameworkValue, string formatExpression)
        {
            DateTime d;
            String s = (frameworkValue != null) ? frameworkValue.ToString() : String.Empty;
            if (DateTime.TryParse(s, out d)) return d.ToString(formatExpression);
            else return null;
        }

        /// <summary>
        /// Tries to convert the specified value
        /// to the <see cref="System.Nullable"/> return type.
        /// </summary>
        /// <param name="frameworkValue">
        /// The specified <see cref="System.Object"/> box.
        /// </param>
        /// <returns>
        /// Always returns a <see cref="System.Nullable"/>
        /// as parse failure means <c>HasValue</c>
        /// is false.
        /// </returns>
        public static Double? ParseDouble(Object frameworkValue)
        {
            Double d;
            String s = (frameworkValue != null) ? frameworkValue.ToString() : String.Empty;
            if (Double.TryParse(s, out d)) return d;
            else return new Double?();
        }

        /// <summary>
        /// Tries to convert the specified value
        /// to the <see cref="System.Nullable"/> return type.
        /// </summary>
        /// <param name="frameworkValue">
        /// The specified <see cref="System.Object"/> box.
        /// </param>
        /// <returns>
        /// Always returns a <see cref="System.Nullable"/>
        /// as parse failure means <c>HasValue</c>
        /// is false.
        /// </returns>
        public static Int32? ParseInt32(Object frameworkValue)
        {
            Int32 i;
            String s = (frameworkValue != null) ? frameworkValue.ToString() : String.Empty;
            if (Int32.TryParse(s, out i)) return i;
            else return new Int32?();
        }

        /// <summary>
        /// Tries to convert the specified value
        /// to a <see cref="System.String"/>.
        /// </summary>
        /// <param name="frameworkValue">
        /// The specified <see cref="System.Object"/> box.
        /// </param>
        public static String ParseString(Object frameworkValue)
        {
            return (frameworkValue != null) ? frameworkValue.ToString() : null;
        }
    }
}
